#ifndef xpack_lang_cxx
#define xpack_lang_cxx
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::lang_cxx::inc
#include"adapter/random_access.hpp"
#include"chrono/datetime.hpp"
#include"define/base_type.hpp"
#include"define/classify.hpp"
#include"interface/can_alloc.hpp"
#include"interface/can_alloc_seq.hpp"
#include"interface/can_callback.hpp"
#include"interface/can_compare.hpp"
#include"interface/initializer_list.hpp"
#include"interface/ranger.hpp"
#include"interface/seqptr.hpp"
#include"interface/unified_seq.hpp"
#include"lang/cxx/private/cxx_helper.hpp"
#include"lang/cxx/private/l_is_secret.hpp"
#include"lang/cxx/private/lut.uri.hpp"
#include"lang/cxx/private/lut.base64x.hpp"
#include"lang/cxx/private/parse_xxx_result.hpp"
#include"macro/xforward.hpp"
#include"macro/xmark+.hpp"
#include"macro/xnew.hpp"
#include"macro/xstruct.hpp"
#include"macro/xsv.hpp"
#include"macro/xthread_local.hpp"
#include"math/index_system.hpp"
#include"math/minimum.hpp"
#include"math/numeration_t.hpp"
#include"meta/ensure.hpp"
#include"meta/has_cast.hpp"
#include"meta/has_constructor.hpp"
#include"meta/integer_type.hpp"
#include"meta/is_base_char.hpp"
#include"meta/is_const.hpp"
#include"meta/is_enum_class.hpp"
#include"meta/is_enum_origin.hpp"
#include"meta/is_float.hpp"
#include"meta/is_integer.hpp"
#include"meta/is_number.hpp"
#include"meta/is_origin_string.hpp"
#include"meta/is_same.hpp"
#include"meta/is_the_xstruct.hpp"
#include"meta/is_xstruct_prop.hpp"
#include"meta/item_origin_of.hpp"
#include"meta/origin_of.hpp"
#include"meta/prop_type.hpp"
#include"meta/remove_ref.hpp"
#include"meta/unsigned_type.hpp"
#include"meta_seq/tget.hpp"
#include"meta_seq/tin.hpp"
#include"meta_seq/tlist.hpp"
#include"utils/get_last.hpp"
#include"utils/stream_wrapper.hpp"
#pragma pop_macro("xuser")

namespace mixc::utils_mix_item::origin{
    template<class item_t> struct mix_item;
}

namespace mixc::lang_cxx::inner{
    using inc::l_is_secret;
}

namespace mixc::lang_cxx{
    template<class item_t>
    struct parse_json_result;

    struct utc_date_t;

    template<class seq_t>
    using parse_base64_result       = parse_xxx_result<seq_t>;

    template<class seq_t>
    using parse_base64uri_result    = parse_xxx_result<seq_t>;

    template<class seq_t>
    using parse_uri_result          = parse_xxx_result<seq_t>;

    using parse_utc_date_result     = parse_xxx_result<inc::datetime>;

    template<class value_t>
    using parse_result              = parse_xxx_result<value_t>;

    enum binaray_option_list_t : uxx{
        the_make_json_string,
        the_keep_separator,
    };

    using make_json_string_t        = binaray_option<the_make_json_string>;
    using keep_separator_t          = binaray_option<the_keep_separator>;

    constexpr keep_separator_t keep_separator(true);



    template<inc::is_base_char char_t>
    struct encode_first_as_result;

    xstruct(
        xname(cxx_index_pair),
        xprif(m_i_main, uxx),
        xprif(m_i_pattern, uxx)
    )
        xprops()
            xpubget_pubset(i_main, uxx);
            xpubget_pubset(i_pattern, uxx);
        $

        xprops_operator()
    public:
        operator uxx() const {
            return m_i_main;
        }
    $

    xstruct(
        xname(cxx_position),
        xprif(m_i_th, uxx),
        xprif(m_offset, uxx)
    )
    public:
        xprops()
            xpubget_pubset(i_th, uxx);
            xpubget_pubset(offset, uxx);
        $

        xprops_operator()

        operator uxx() const {
            return m_offset;
        }
    $

    template<class cxx_t, class type_t>
    constexpr bool is_valid_parse_type =
        inc::is_base_char<
            inc::origin_of<type_t, with_propcast>
        > or
        inc::is_same<
            inc::origin_of<type_t, with_propcast>, cxx_t
        > or
        inc::is_number<
            inc::origin_of<type_t, with_propcast>
        >;
    
    template<class cxx_t, class ... type_t>
    constexpr bool is_valid_parse_type_list = (... and is_valid_parse_type<cxx_t, type_t>);

    template<class item_t>
    struct cxx_split_result;

    enum class float_format_t;
    enum class int_format_t;
}

namespace mixc::lang_cxx::origin{
    using mixc::lang_cxx::parse_base64_result;
    using mixc::lang_cxx::parse_base64uri_result;
    using mixc::lang_cxx::parse_result;
    using mixc::lang_cxx::encode_first_as_result;
    using mixc::lang_cxx::cxx_index_pair;
    using mixc::lang_cxx::cxx_position;
    using mixc::lang_cxx::float_format_t;
    using mixc::lang_cxx::int_format_t;
}

namespace mixc::lang_cxx{
    namespace inc{
        using ::mixc::utils_mix_item::origin::mix_item;
    }

    template<class item_type_t>
    xstruct(
        xtmpl(cxx, item_type_t),
        xpubb(inc::random_access<cxx<item_type_t>, item_type_t>),
        xprif_no_mut(m_ptr, item_type_t *),
        xprif_no_mut(m_length, uxx),  // 使用 no_mut 确保支持 constexpr cxx 数组
        xwhos(inc::classify_t::lang_cxx)
    )
    public:
        xmark_is_string_wrapper();
    public:
        using item_t                = item_type_t;
        using item_cref_t           = item_t const &;
        using the_cref_t            = the_t const &;
        using mix_item              = inc::mix_item<item_t>;

        template<class char_t>
        using allocx_t              = inc::ialloc<char_t> const &;
        using alloc_t               = inc::ialloc<item_t> const &;

        template<class char_t>
        using streamx_t             = inc::stream_wrapperx<char_t> const &;
        using stream_t              = inc::stream_wrapperx<item_t> const &;

        using invoke_count_of_t     = inc::icallback<bool(uxx index, item_cref_t item)> const &;
        using invoke_find_t         = inc::icallback<loop_t(cxx_position position), loop_t::go_on> const &;
        using invoke_split_t        = inc::icallback<void(cxx_split_result<item_t> const &)> const &;
        using invoke_compare_t      = inc::icompare<item_t> const &;

        // 这里使用 ensure 代替 requires 可以做到
        // - 兼容憨憨 msvc 编译器
        // - 简化函数体参数
        // ==============================================================================
        #define xcxx_header_item_seq                                                \
            class item_seq_t = inc::initializer_list<item_t>,                       \
            class = inc::ensure<                                                    \
                inc::is_unified_seqx<item_seq_t, item_t> or (                       \
                    inc::can_unified_seqlizex<item_seq_t, item_t> and               \
                    inc::has_constructor<cxx<item_t>, item_seq_t/*隐式构造*/> == false    \
                )                                                                   \
            >
        #define xcxx_header_the_t_seq                                               \
            class seq_t = inc::initializer_list<the_t>,                             \
            class = inc::ensure<                                                    \
                inc::can_unified_seqlizex<seq_t, the_t> or                          \
                inc::can_unified_seqlizex<seq_t, const the_t>/* 支持 constexpr cxx*/\
            >,                                                                      \
            class = void/*避免和 xcxx_header_item_seq 一样*/

        #define __xcxx_header_format(N,...)                                         \
            sizeof...(args_t) > N and                                               \
                                                                                    \
            inc::can_rangerlizex<                                                   \
                inc::tget<                                                          \
                    inc::tlist<args_t...>, 0                                        \
                >,                                                                  \
                inc::mix_item<item_t>                                               \
            > == false and                                                          \
                                                                                    \
            /* 要求最后一个参数满足 ialloc<T> 约束*/                                \
            helper::template is_xalloc<                                             \
                inc::tget<                                                          \
                    inc::tlist<args_t...>, -1/*最后一个*/                           \
                >                                                                   \
            >

        #define xcxx_header_format          __xcxx_header_format(0)
        #define xcxx_header_logger_helper   __xcxx_header_format(1)

        using helper = inc::cxx_helper<item_t>;

        friend helper;

    public: // 属性区
        xprops()
            xpubget_pubset(length, uxx);

            xpubgetx(is_empty, bool){
                xr{ return xthe.m_length == 0; }
            };

            xpubgetx(is_cstr_compatible, bool){
                xr{ return xthe.m_ptr[xthe.m_length] == '\0'; }
            };
        $

        xprops_operator()

    public: // 基本构造函数区
        constexpr cxx() : cxx(helper::empty, 0) {}

        template<uxx length_v>
        constexpr cxx(item_t str[length_v]) : 
            cxx(str, length_v - 1){
        }

        constexpr cxx(item_t const * str) : 
            m_ptr((item_t *)str), m_length(0) {

            if (m_ptr == nullptr){
                m_ptr               = helper::empty;
            }

            while(m_ptr[m_length]){
                m_length           += 1;
            }
        }

        // 和 xcxx_header_item_seq 冲突
        // 像 cxx::find() 等接口，参数可能为字符数组，需要区分字符数组和字符串
        // 支持 seqptr 类型隐含数组性质，所以需要显示指明
        // 
        // 此外
        // 如果一个类型带有类似 operator asciis() 的运算符重载，
        // 而直接使用使用 seqptr<item_t> 作为构造函数参数将无法让 cxx 区分是走 cxx(item_t const *) 重载还是此重载，
        // 所以显式指明要求此构造函数为 seqptr<> 类型，而非来自隐式转换
        template<inc::is_seqptr seq_t>
        explicit constexpr cxx(seq_t && value) : 
            cxx((item_t *)value, value->length) {
        }

        template<class type_t>
        constexpr cxx(type_t const * ptr, uxx length) : 
            m_ptr(ptr ? (item_t *)ptr : helper::empty), m_length(ptr ? length : 0) {
            static_assert(sizeof(type_t) == sizeof(item_t));
        }

        constexpr cxx(inc::static_string_holder<item_t> holder) : 
            cxx(holder.ptr(), holder.length()){
        }

        template<class type_t>
        requires(inc::has_constructor<the_t, void(type_t &&)/*支持显式够构造*/>)
        the_t & operator=(type_t && value){
            xnew(this) the_t(xforward(value));
            return xthe;
        }

        explicit operator item_t *() const {
            // 使用 explicit 避免出现在未包含 "lang/cxx/compare_xxx.hpp" 时直接变成指针比较 
            return xthe.m_ptr;
        }

        constexpr uxx length() const {
            return m_length; // 对外提供 constexpr 版本 length
        }

        the_t backward(uxx value) const {
            auto tmp        = xthe;
            tmp.m_ptr      += value;
            tmp.m_length   -= uxx(value);
            return tmp;
        }

        the_t forward(uxx value) const {
            return backward(
                uxx(-ixx(value))
            );
        }

        the_t shorten(uxx length) const {
            auto tmp        = xthe;
            tmp.m_length   -= length;
            return tmp;
        }

        the_t elongate(uxx length) const {
            return shorten(
                uxx(-ixx(length))
            );
        }

        template<class cmp_t = decltype(inc::default_compare<item_t>)>
        requires(inc::can_compare<cmp_t, item_t>)
        ixx compare(the_cref_t value, cmp_t const & compare = inc::default_compare<item_t>) const {
            uxx len = inc::minimum<uxx>(xthe->length, value->length);

            for(uxx i = 0; i < len; i++){
                if (ixx r = compare(xthe[i], value[i]); r != 0){
                    return r;
                }
            }
            return ixx(xthe->length - value->length);
        }

        #define xa_args_list       the_t const & left, the_t const & right
        #define xa_invoke          left.compare(right)
        #define xa_is_friend
        #include"macro/xgen.cmp.hpp"

        #define xa_args_list       item_t const * left, the_t const & right
        #define xa_invoke          the_t(left).compare(right)
        #define xa_is_friend
        #include"macro/xgen.cmp.hpp"

        #define xa_args_list       the_t const & left, item_t const * right
        #define xa_invoke          left.compare(the_t{right})
        #define xa_is_friend
        #include"macro/xgen.cmp.hpp"

    private:
        template<class lambda_t>
        static auto stream_return_type(){
            if constexpr (not helper::template can_stream<lambda_t>){
                return the_t{};
            }
        }
    public:

        #define xcxx_header_alloc                                               \
            class xalloc_t,                                                     \
            class ret_t = decltype(stream_return_type<xalloc_t>()),             \
            class = inc::ensure<helper::template is_xalloc<xalloc_t>>

        #define xcxx_header_allocx(...)                                         \
            __VA_ARGS__,                                                        \
            class xalloc_t,                                                     \
            class ret_t = decltype(stream_return_type<xalloc_t>()),             \
            class = inc::ensure<helper::template is_xalloc<xalloc_t>>

        template<xcxx_header_alloc> ret_t align_center(uxx width, xalloc_t const & alloc) const;
        template<xcxx_header_alloc> ret_t align_center(uxx width, item_cref_t pad, xalloc_t const & alloc) const;
        template<xcxx_header_alloc> ret_t align_center(uxx width, item_cref_t pad_left, item_cref_t pad_right, xalloc_t const & alloc) const;

        template<xcxx_header_alloc> ret_t align_left(uxx width, xalloc_t const & alloc) const;
        template<xcxx_header_alloc> ret_t align_left(uxx width, item_cref_t pad, xalloc_t const & alloc) const;


        template<xcxx_header_alloc> ret_t align_right(uxx width, xalloc_t const & alloc) const;
        template<xcxx_header_alloc> ret_t align_right(uxx width, item_cref_t pad, xalloc_t const & alloc) const;


        template<xcxx_header_alloc> ret_t clone(xalloc_t const & alloc) const;


        uxx count_of(the_cref_t pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;
        uxx count_of(item_cref_t pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;
        uxx count_of(invoke_count_of_t iterator) const;


        template<inc::is_base_char char_t>
        encode_first_as_result<char_t> encode_first_as() const;

        template<inc::is_base_char char_t>
        cxx<char_t> encode_item_as(allocx_t<char_t> alloc) const;

        template<inc::is_base_char char_t>
        void encode_item_as(streamx_t<char_t> stream) const;


        template<xcxx_header_item_seq>
        uxx find_reverse(item_seq_t const & pattern_list, invoke_find_t when_match) const;

        template<xcxx_header_item_seq>
        uxx find_reverse(item_seq_t const & pattern_list, invoke_compare_t compare, invoke_find_t when_match) const;

        template<xcxx_header_item_seq>
        uxx find_reverse(item_seq_t const & pattern_list, ixx n_th, invoke_compare_t compare = inc::default_compare<item_t>) const;

        uxx find_reverse(item_cref_t pattern, invoke_find_t when_match) const;
        uxx find_reverse(item_cref_t pattern, invoke_compare_t compare, invoke_find_t when_match) const;
        uxx find_reverse(item_cref_t pattern, ixx n_th, invoke_compare_t compare = inc::default_compare<item_t>) const;

        uxx find_reverse(the_cref_t pattern, invoke_find_t when_match) const;
        uxx find_reverse(the_cref_t pattern, invoke_compare_t compare, invoke_find_t when_match) const;
        uxx find_reverse(the_cref_t pattern, ixx n_th, invoke_compare_t compare = inc::default_compare<item_t>) const;


        template<xcxx_header_item_seq>
        uxx find(item_seq_t const & pattern, invoke_find_t when_match) const;

        template<xcxx_header_item_seq>
        uxx find(item_seq_t const & pattern, invoke_compare_t compare, invoke_find_t when_match) const;

        template<xcxx_header_item_seq>
        uxx find(item_seq_t const & pattern, ixx n_th, invoke_compare_t compare = inc::default_compare<item_t>) const;


        uxx find(item_cref_t pattern, invoke_find_t when_match) const;
        uxx find(item_cref_t pattern, invoke_compare_t compare, invoke_find_t when_match) const;
        uxx find(item_cref_t pattern, ixx n_th, invoke_compare_t compare = inc::default_compare<item_t>) const;

        uxx find(the_cref_t pattern, invoke_find_t match) const;
        uxx find(the_cref_t pattern, invoke_compare_t compare, invoke_find_t when_match) const;
        uxx find(the_cref_t pattern, ixx n_th, invoke_compare_t compare = inc::default_compare<item_t>) const;

        template<class ... args_t>
        requires(xcxx_header_format) // 兼容 msvc，
        auto format(args_t && ... args) const {
            auto && alloc           = inc::get_last(xforward(args)...);
            mix_item items[]        = { xforward(args)... };

            // 注意：
            // 如果 inc::ranger<mix_item>{ items, items_length }; 
            // 将会走 constexpr ranger(inc::initializer_list<item_t> const & seq); 这个重载
            // 需要使用小括号才表示两个参数，用花括号会被当成 initializer_list 
            auto list               = inc::ranger<mix_item>(items, sizeof...(args_t) - 1);
            return xthe.format(list, alloc);
        }

        template<class ... args_t>
        requires(xcxx_header_format)
        auto format_non_secret(args_t && ... args) const { // 兼容 msvc，
            auto && alloc           = inc::get_last(xforward(args)...);
            mix_item items[]        = { xforward(args)... };

            // 注意：
            // 如果 inc::ranger<mix_item>{ items, items_length }; 
            // 将会走 constexpr ranger(inc::initializer_list<item_t> const & seq); 这个重载
            // 需要使用小括号才表示两个参数，用花括号会被当成 initializer_list 
            auto list               = inc::ranger<mix_item>(items, sizeof...(args_t) - 1);
            return xthe.format_non_secret(list, alloc);
        }

    private:
        template<xcxx_header_alloc>
        ret_t format_core(bool is_secret, inc::ranger<mix_item> const & list, xalloc_t const & alloc) const;

    public:
        template<xcxx_header_alloc>
        ret_t format(inc::ranger<mix_item> const & list, xalloc_t const & alloc) const {
            return this->format_core(true, list, alloc);
        }

        template<xcxx_header_alloc>
        ret_t format_non_secret(inc::ranger<mix_item> const & list, xalloc_t const & alloc) const {
            return this->format_core(false, list, alloc);
        }


        template<xcxx_header_item_seq>
        uxx index_of_first_miss(item_seq_t const & pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;

        template<xcxx_header_the_t_seq>
        uxx index_of_first_miss(seq_t && pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;
        uxx index_of_first_miss(item_cref_t pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;
        uxx index_of_first_miss(the_cref_t pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;


        template<xcxx_header_item_seq>
        cxx_index_pair index_of_first(item_seq_t const & pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;
        uxx index_of_first(item_cref_t pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;
        uxx index_of_first(the_cref_t pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;


        template<xcxx_header_item_seq>
        uxx index_of_last_miss(item_seq_t const & pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;

        template<xcxx_header_the_t_seq>
        uxx index_of_last_miss(seq_t && pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;
        uxx index_of_last_miss(item_cref_t pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;
        uxx index_of_last_miss(the_cref_t pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;


        template<xcxx_header_item_seq>
        cxx_index_pair index_of_last(item_seq_t const & pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;
        uxx index_of_last(item_cref_t pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;
        uxx index_of_last(the_cref_t pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;


        template<xcxx_header_item_seq>
        uxx index_of_prefix(item_seq_t const & pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;

        template<xcxx_header_the_t_seq>
        uxx index_of_prefix(seq_t && pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;


        template<xcxx_header_item_seq>
        uxx index_of_suffix(item_seq_t const & pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;

        template<xcxx_header_the_t_seq>
        uxx index_of_suffix(seq_t && pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;


        template<xcxx_header_alloc> ret_t insert(ixx index, item_cref_t value, xalloc_t const & alloc) const;
        template<xcxx_header_alloc> ret_t insert(ixx index, the_cref_t value, xalloc_t const & alloc) const;


        bool is_contains(item_cref_t value, invoke_compare_t compare = inc::default_compare<item_t>) const;
        bool is_contains(the_cref_t value, invoke_compare_t compare = inc::default_compare<item_t>) const;


        bool is_ends_with(item_cref_t value, invoke_compare_t compare = inc::default_compare<item_t>) const;
        bool is_ends_with(the_cref_t value, invoke_compare_t compare = inc::default_compare<item_t>) const;
        bool is_starts_with(item_cref_t value, invoke_compare_t compare = inc::default_compare<item_t>) const;
        bool is_starts_with(the_cref_t value, invoke_compare_t compare = inc::default_compare<item_t>) const;


        template<inc::is_base_char char_t>
        uxx length_if_item_as() const;


    private:
        template<xcxx_header_alloc>
        ret_t logger_helper_core(bool is_secret, inc::ranger<mix_item> const & list, xalloc_t const & alloc) const;

    public:
        template<class ... args_t>
        requires(xcxx_header_logger_helper)
        auto logger_helper(args_t const & ... args) const { // 兼容 msvc，
            mix_item items[]      = { args... };
            auto &&  alloc        = inc::get_last(args...);

            // 注意：
            // 如果 inc::ranger<mix_item>{ items, items_length }; 
            // 将会走 constexpr ranger(inc::initializer_list<item_t> const & seq); 这个重载
            // 需要使用小括号才表示两个参数，用花括号会被当成 initializer_list 
            auto   list         = inc::ranger<mix_item>(items, sizeof...(args_t) - 1);
            return xthe.logger_helper(list, alloc);
        }

        template<class ... args_t>
        requires(xcxx_header_logger_helper)
        auto logger_helper_non_secret(args_t const & ... args) const { // 兼容 msvc，
            mix_item items[]        = { args... };
            auto && alloc           = inc::get_last(args...);

            // 注意：
            // 如果 inc::ranger<mix_item>{ items, items_length }; 
            // 将会走 constexpr ranger(inc::initializer_list<item_t> const & seq); 这个重载
            // 需要使用小括号才表示两个参数，用花括号会被当成 initializer_list 
            auto list               = inc::ranger<mix_item>(items, sizeof...(args_t) - 1);
            return xthe.logger_helper_non_secret(list, alloc);
        }

        template<xcxx_header_alloc>
        auto logger_helper(inc::ranger<mix_item> const & list, xalloc_t const & alloc) const {
            return this->logger_helper_core(true, list, alloc);
        }

        template<xcxx_header_alloc>
        auto logger_helper_non_secret(inc::ranger<mix_item> const & list, xalloc_t const & alloc) const {
            return this->logger_helper_core(false, list, alloc);
        }


        template<xcxx_header_allocx(inc::can_unified_seqlize seq_t)>
        cxx(base64_t const & mode, seq_t && seq, xalloc_t const & alloc);


        template<class object_t, xcxx_header_alloc>
        cxx(make_json_string_t mode, object_t const & object, xalloc_t const & alloc);

        template<class object_t, xcxx_header_alloc>
        cxx(make_json_string_t mode, object_t const & object, the_cref_t pad, xalloc_t const & alloc);

        template<xcxx_header_allocx(inc::can_unified_seqlize seq_t)>
        requires(sizeof(inc::item_origin_of<seq_t>) <= 4) 
        cxx(uri_t const & mode, seq_t && seq, xalloc_t const & alloc);


        template<xcxx_header_allocx(inc::is_datetime datetime_t)>
        cxx(utc_date_t const & lut, datetime_t const & datetime, xalloc_t const & alloc);


        template<xcxx_header_alloc> ret_t pad_bends(uxx left_count, uxx right_count, item_cref_t pad, xalloc_t const & alloc) const;
        template<xcxx_header_alloc> ret_t pad_bends(uxx left_count, uxx right_count, item_cref_t pad_left, item_cref_t pad_right, xalloc_t const & alloc) const;
        template<xcxx_header_alloc> ret_t pad_left(uxx count, item_cref_t value, xalloc_t const & alloc) const;
        template<xcxx_header_alloc> ret_t pad_right(uxx count, item_cref_t value, xalloc_t const & alloc) const;


        template<inc::can_alloc_seq alloc_seq_t>
        auto parse_base64(alloc_seq_t const & alloc) const;

        template<inc::can_alloc_seq alloc_seq_t>
        auto parse_base64uri(alloc_seq_t const & alloc) const;


        parse_json_result<item_t> parse_json(allocx_t<void> alloc) const;


        template<inc::can_alloc_seq alloc_seq_t>
        auto parse_uri(alloc_seq_t const & alloc) const;


        parse_utc_date_result parse_utc_date() const;


        template<class target_t>
        parse_result<target_t> parse() const;

        template<class target_t>
        requires(inc::is_float<target_t> == false)
        parse_result<target_t> parse(inc::numeration_t raidx) const;

        parse_result<uxx> parse(the_t & first) const {
            return xthe.parse("", first);
        }

    private:
        // clang11 对带折叠表达式 requires 语句的成员函数可能存在误报，
        // 所以让 parse 的实现在一个无需此语句的成员子函数中实现
        template<class first_t, class ... rest_t>
        parse_result<uxx> parse_list(the_cref_t fmt, first_t && first, rest_t && ... rest) const;
    public:
        template<class first_t, class ... rest_t>
        requires(
            (inc::is_origin_string<first_t> == false and inc::is_cxx<first_t> == false) and
            (is_valid_parse_type_list<the_t, first_t, rest_t...>)
        )
        parse_result<uxx> parse(first_t && first, rest_t && ... rest) const {
            return xthe.parse_list("", ((first_t &&)first), ((rest_t &&)rest)...);
        }

        template<class first_t, class ... rest_t>
        requires(is_valid_parse_type_list<the_t, first_t, rest_t...>)
        parse_result<uxx> parse(the_cref_t fmt, first_t && first, rest_t && ... rest) const {
            return xthe.parse_list(fmt, (first_t &&)first, (rest_t &&)rest...);
        }

        template<xcxx_header_allocx(inc::can_interval interval_t)>
        ret_t remove(interval_t range, xalloc_t const & alloc) const;


        template<xcxx_header_alloc>
        ret_t replace(the_cref_t old_value, the_cref_t new_value, xalloc_t const & alloc) const;
        the_t replace(the_cref_t old_value, the_cref_t new_value, invoke_compare_t compare, alloc_t alloc) const;
        void replace(the_cref_t old_value, the_cref_t new_value, invoke_compare_t compare, stream_t alloc) const;


        template<xcxx_header_alloc> ret_t reverse(xalloc_t const & alloc) const;


        template<xcxx_header_item_seq>
        void split(item_seq_t const & separator_list, invoke_split_t receive) const;

        template<xcxx_header_item_seq>
        void split(item_seq_t const & separator_list, invoke_compare_t compare, invoke_split_t receive) const;

        template<xcxx_header_item_seq>
        void split(item_seq_t const & separator_list, keep_separator_t keep_separator, invoke_split_t receive) const;

        template<xcxx_header_item_seq>
        void split(item_seq_t const & separator_list, keep_separator_t keep_separator, invoke_compare_t compare, invoke_split_t receive) const;

        void split(item_cref_t separator, invoke_split_t receive) const;
        void split(item_cref_t separator, invoke_compare_t compare, invoke_split_t receive) const;
        void split(item_cref_t separator, keep_separator_t keep_separator, invoke_split_t receive) const;
        void split(item_cref_t separator, keep_separator_t keep_separator, invoke_compare_t compare, invoke_split_t receive) const;
        void split(the_cref_t separator, invoke_split_t receive) const;
        void split(the_cref_t separator, invoke_compare_t compare, invoke_split_t receive) const;
        void split(the_cref_t separator, keep_separator_t keep_separator, invoke_split_t receive) const;
        void split(the_cref_t separator, keep_separator_t keep_separator, invoke_compare_t compare, invoke_split_t receive) const;


        template<inc::can_interval interval_t>
        the_t slice(interval_t range) const;

        template<xcxx_header_allocx(inc::can_interval interval_t)>
        ret_t slice(interval_t range, xalloc_t const & alloc) const;


        template<xcxx_header_the_t_seq, xcxx_header_alloc>
        ret_t strcat(seq_t && values, xalloc_t const & alloc) const;

        template<xcxx_header_alloc>
        ret_t strcat(the_cref_t value, xalloc_t const & alloc) const;

        template<inc::is_xstruct_prop prop_t, xcxx_header_alloc>
        requires(
            inc::has_constructor<the_t, void(inc::prop_type<prop_t>, xalloc_t)>
        )
        cxx(prop_t && prop, xalloc_t const & alloc) : cxx(prop(), alloc){} // 支持 xstruct 属性

        template<inc::is_integer number_t, xcxx_header_alloc>
        cxx(number_t value, int_format_t fmt, inc::numeration_t radix, asciis lut, xalloc_t const & alloc);

        template<inc::is_integer number_t, xcxx_header_alloc>
        cxx(number_t value, int_format_t fmt, inc::numeration_t radix, xalloc_t const & alloc);

        template<inc::is_integer number_t, xcxx_header_alloc>
        cxx(number_t value, inc::numeration_t radix, asciis lut, xalloc_t const & alloc);

        template<inc::is_integer number_t, xcxx_header_alloc>
        cxx(number_t value, inc::numeration_t radix, xalloc_t const & alloc);

        template<inc::is_integer number_t, xcxx_header_alloc>
        cxx(number_t value, xalloc_t const & alloc);

        template<inc::is_float float_t, xcxx_header_alloc>
        cxx(float_t value, float_format_t mode, uxx precious, xalloc_t const & alloc);

        template<inc::is_float float_t, xcxx_header_alloc>
        cxx(float_t value, uxx precious, xalloc_t const & alloc);

        template<inc::is_float float_t, xcxx_header_alloc>
        cxx(float_t value, float_format_t mode, xalloc_t const & alloc);

        template<inc::is_float float_t, xcxx_header_alloc>
        cxx(float_t value, xalloc_t const & alloc);

        template<xcxx_header_alloc>
        cxx(the_cref_t value, xalloc_t const & alloc);

        template<xcxx_header_alloc>
        cxx(item_cref_t value, xalloc_t const & alloc);

        template<xcxx_header_alloc>
        cxx(item_t const * value, xalloc_t const & alloc);

        template<xcxx_header_alloc>
        cxx(bool value, xalloc_t const & alloc);

        template<inc::is_date date_t, xcxx_header_alloc>
        cxx(date_t date, xalloc_t const & alloc);

        template<inc::is_time time_t, xcxx_header_alloc>
        cxx(time_t time, xalloc_t const & alloc);

        template<inc::is_datetime datetime_t, xcxx_header_alloc>
        cxx(datetime_t datetime, xalloc_t const & alloc);

        template<inc::is_enum_origin enum_t, xcxx_header_alloc>
        cxx(enum_t value, xalloc_t const & alloc) : cxx(inc::integer_type<enum_t>(value), alloc){}

        template<inc::is_enum_class enum_t, xcxx_header_alloc>
        cxx(enum_t value, xalloc_t const & alloc) : cxx(inc::unsigned_type<enum_t>(value), alloc){}

        template<xcxx_header_alloc>
        cxx(secret_mark_t secret, xalloc_t const & alloc) : cxx((item_t const *)secret, alloc){}

        template<
            class secret_prop_t,
            class secret_t = inc::origin_of<secret_prop_t, with_propcast>,
            class origin_t = typename secret_t::origin_type,
            xcxx_header_alloc
        >
        requires(
            inc::is_secret_type<secret_t> and
            inc::has_constructor<cxx<item_t>, void(origin_t, xalloc_t const &)>
        )
        cxx(secret_prop_t && value, xalloc_t const & alloc){
            if (*inner::l_is_secret){
                xnew(this) the_t(::secret_mark, alloc);
            }
            else{
                xnew(this) the_t((origin_t)(secret_t)(value), alloc);
            }
        }

        static bool is_in_secret(){
            return *inner::l_is_secret;
        }

        template<xcxx_header_item_seq>
        the_t trim_bends(item_seq_t const & pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;

        template<xcxx_header_the_t_seq>
        the_t trim_bends(seq_t && pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;
        the_t trim_bends(item_cref_t pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;
        the_t trim_bends(the_cref_t pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;


        template<xcxx_header_item_seq>
        the_t trim_end(item_seq_t const & pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;

        template<xcxx_header_the_t_seq>
        the_t trim_end(seq_t && pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;
        the_t trim_end(item_cref_t pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;
        the_t trim_end(the_cref_t pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;


        template<xcxx_header_item_seq>
        the_t trim_start(item_seq_t const & pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;

        template<xcxx_header_the_t_seq>
        the_t trim_start(seq_t && pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;
        the_t trim_start(item_cref_t pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;
        the_t trim_start(the_cref_t pattern, invoke_compare_t compare = inc::default_compare<item_t>) const;

    private:
        friend inc::random_access<the_t, item_type_t>;

        item_t & random_get(uxx index) const {
            return xthe.m_ptr[index];
        }
    $
}

namespace mixc::lang_cxx::origin{
    using mixc::lang_cxx::cxx;
    using c08 = cxx<char>;
    using c16 = cxx<char16_t>;
}

#if xis_os64
    #define xc08(str)      xsv(char, "0123456789abcdef", str)
#elif xis_os32
    #define xc08(str)      xsv(char, "01234567", str)
#endif

#define xmake_cxx(...)      { __VA_ARGS__, sizeof(__VA_ARGS__) / sizeof(__VA_ARGS__[0]) - 1 }

#undef  xcxx_header_item_seq
#undef  xcxx_header_the_t_seq
#undef  xcxx_header_logger_helper
#undef  xcxx_header_alloc
#undef  xcxx_header_allocx
#endif

xexport_space(mixc::lang_cxx::origin)
